package meminin.naivebayes;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import meminin.model.Label;

/**
 *
 * @author Danang
 */
public class NaiveBayesProbabilityModel {
    private NaiveBayesTrainingData trainingData;
    private NaiveBayesDataRecord dataRecord;
    private HashMap<String, NaiveBayesModel> model; // per attrib
    private NaiveBayesLabel classLabel;
    
    public NaiveBayesProbabilityModel(String filePath, String hostName, String dbName, String tableName, String dbUser, String dbPassword){
        trainingData = new NaiveBayesTrainingData(filePath, hostName, dbName, tableName, dbUser, dbPassword);
        dataRecord = new NaiveBayesDataRecord();
        model = new HashMap<String, NaiveBayesModel>();
        trainingData.readTrainingData();
        classLabel = (NaiveBayesLabel) trainingData.getClassLabel();
        
        generateModel();
        
    }

    /**
     * @return the trainingData
     */
    public NaiveBayesTrainingData getTrainingData() {
        return trainingData;
    }

    /**
     * @param trainingData the trainingData to set
     */
    public void setTrainingData(NaiveBayesTrainingData trainingData) {
        this.trainingData = trainingData;
    }

    /**
     * @return the dataRecord
     */
    public NaiveBayesDataRecord getDataRecord() {
        return dataRecord;
    }

    /**
     * @param dataRecord the dataRecord to set
     */
    public void setDataRecord(NaiveBayesDataRecord dataRecord) {
        this.dataRecord = dataRecord;
    }

    private void generateModel() {
        ArrayList<Label> allAttributes = trainingData.getLabels();
        ArrayList<String> classLabelValues = classLabel.getValues();
        HashMap<String, Integer> classFrequency = new HashMap<String, Integer>();
        int total=0;
        for (String s : classLabelValues) {
            // where classLabel.getDesc = s
            int count = trainingData.getCountFromQuery(dataRecord.getReadQueryWhereClass(
                    trainingData.getDbName(), trainingData.getTableName(), classLabel.getDesc(), s));
            total += count;
            classFrequency.put(s, count);
        }
        for (Label s : allAttributes) {
            NaiveBayesLabel nl = (NaiveBayesLabel) s;
            if (!nl.isIsClassAtribute()) {
                ArrayList<String> labelValues = nl.getValues();
                NaiveBayesModel nbm = new NaiveBayesModel();
                for (String lv : labelValues) {
                    NaiveBayesClassModel nbcm = new NaiveBayesClassModel();
                    for (String clv : classLabelValues) {
                        // where nl.getDesc = lv and classLabel.getDesc = clv
                        int count = trainingData.getCountFromQuery(dataRecord.getReadQueryWhereClassAndAttrib(
                                trainingData.getDbName(), trainingData.getTableName(), 
                                nl.getDesc(), lv, classLabel.getDesc(), clv));
                        double prob = (double) count/classFrequency.get(clv);
                        nbcm.addKeyAndValue(clv, prob);
                    }
                    nbm.addAttribValueProbability(lv, nbcm);
                }
                model.put(nl.getDesc(), nbm);
            } else {
                NaiveBayesModel nbm = new NaiveBayesModel();
                NaiveBayesClassModel nbcm = new NaiveBayesClassModel();
                for (String clv : classLabelValues) {
                    double prob = (double) classFrequency.get(clv)/total;
                    nbcm.addKeyAndValue(clv, prob);
                }
                nbm.addAttribValueProbability(classLabel.getDesc(), nbcm);
                model.put(nl.getDesc(), nbm);
            }
        }
    }
    
    public void printModelProbability() {
        ArrayList<Label> allAttributes = trainingData.getLabels();
        ArrayList<String> classLabelValues = classLabel.getValues();
        for (Label s : allAttributes) {
            NaiveBayesLabel nl = (NaiveBayesLabel) s;
            NaiveBayesModel nbm = model.get(nl.getDesc());
            ArrayList<String> labelValues = nl.getValues();
            for (String t : labelValues) {
                NaiveBayesClassModel nbcm = null;
                if (!nl.isIsClassAtribute()) {
                    nbcm = nbm.getProbabilityFromAttribValue(t);
                } else {
                    nbcm = nbm.getProbabilityFromAttribValue(classLabel.getDesc());
                }
                for (String clv : classLabelValues) {
                    System.out.println(nl.getDesc()+"="+t+" "+clv+" "+nbcm.getValueFromKey(clv));
                }
            }
        }
    }

    public String klasifikasi(HashMap<String, String> attribValues) {
        ArrayList<String> tempKeys = new ArrayList<String>();
        Iterator it = attribValues.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry) it.next();
            tempKeys.add((String) pairs.getKey());
        }
        
        ArrayList<String> classLabelValues = classLabel.getValues();
        NaiveBayesClassModel classProb = ((NaiveBayesModel) model.get(classLabel.getDesc())).getProbabilityFromAttribValue(classLabel.getDesc());
        double maks=0;
        String klasifikasi="";        
        for (String clv : classLabelValues) {
            double p = classProb.getValueFromKey(clv);
            for (String s : tempKeys) {
                NaiveBayesClassModel nbm = ((NaiveBayesModel)model.get(s)).getProbabilityFromAttribValue(attribValues.get(s));
                p = p * nbm.getValueFromKey(clv);
            }
            if (p>=maks) {
                maks = p;
                klasifikasi = clv;
            }
        }
        
        return klasifikasi;
    }
}
